#include <types.h>
#include <sys_config.h>
#include <retcode.h>
#include <api/libc/string.h>
#include <api/libc/printf.h>
#include <osal/osal.h>
#include <hld/hld_dev.h>
#include <hld/dis/VPO.h>
#include <hld/decv/vdec_driver.h>
#include <hld/decv/decv.h>
#include <hld/deca/deca_dev.h>
#include <hld/deca/deca.h>
#include <hld/snd/snd_dev.h>
#include <hld/snd/snd.h>
#include <api/libtsi/db_3l.h>
#include <hld/decv/decv_media_player.h>

#include <api/libmp/pe.h>
#include "video_engine.h"
#include "plugin.h"
#include "t2mpgdec.h"

//#ifdef SUPPORT_MPEG4_TEST
//#include "../../libmp4dec/decoder/Common/com_def.h"
//#endif

#ifdef DUAL_ENABLE
#include <modules.h>

enum VIDEO_ENGINE_FUNC{
    
    FUNC_VIDEO_ENGINE_INIT = 0,   
    FUNC_VIDEO_ENGINE_PE_CACHE_INIT,
    FUNC_VIDEO_ENGINE_DECODE,   
    FUNC_VIDEO_ENGINE_SET_OUTPUT,
    FUNC_VIDEO_ENGINE_CMD_PLAY,
    FUNC_VIDEO_ENGINE_CMD_PAUSE,
    FUNC_VIDEO_ENGINE_CMD_RESUME,
    FUNC_VIDEO_ENGINE_CMD_FF,
    FUNC_VIDEO_ENGINE_CMD_FB,
    FUNC_VIDEO_ENGINE_CMD_SLOW,
    FUNC_VIDEO_ENGINE_CMD_STOP,
    FUNC_VIDEO_ENGINE_CMD_SEARCH,
    FUNC_VIDEO_ENGINE_CMD_CHANGE_AUDIO_TRACK,
    FUNC_VIDEO_ENGINE_CMD_CHANGE_PROG,
    FUNC_VIDEO_ENGINE_GET_STREAM_INFO,
    FUNC_VIDEO_ENGINE_GET_PLAY_TIME,
    FUNC_VIDEO_ENGINE_GET_TOTAL_PLAY_TIME,
    FUNC_VIDEO_ENGINE_PE_CACHE_RELEASE,
    FUNC_VIDEO_ENGINE_CMD_SEARCH_MS,
    FUNC_VIDEO_ENGINE_CMD_RESUME_STOP,
    FUNC_VIDEO_ENGINE_CMD_CHANGE_SUBTITLE,
    FUNC_VIDEO_ENGINE_GET_CHAPTER_INFO,
    FUNC_VIDEO_ENGINE_DECODER_CONTROL,
    FUNC_VIDEO_ENGINE_GET_NEXT_STATE,
    FUNC_VIDEO_ENGINE_GET_TOTAL_PLAY_TIMEMS,
    FUNC_VIDEO_ENGINE_GET_PLAY_TIMEMS,
    FUNC_VIDEO_ENGINE_SET_AVSYNC_DELAY,
    FUNC_DECV_DECORE_IOCTL,
    FUNC_DECA_DECORE_IOCTL,
    FUNC_VIDEO_SET_DISALBE_SEEK,
};

#ifndef _LIB_PE_ADV_VIDEO_ENGINE_REMOTE

int video_engine_init(struct pe_video_cfg *pe_video_cfg);
int video_engine_pe_cache_init(pe_cache *pe_cache_info, pe_cache_cmd *pe_cache_cmd_buf, ID pe_cache_mutex);
int video_engine_pe_cache_release();
int video_engine_decode(char *video_file, UINT8 video_stream_type, enum SndDupChannel audio_channel, BOOL preview);
int video_engine_set_output(enum VDecOutputMode eOutMode, struct VDecPIPInfo *pInitInfo);
DWORD mpg_cmd_play_proc();
DWORD mpg_cmd_pause_proc();
DWORD mpg_cmd_resume_proc();
DWORD mpg_cmd_ff_proc();
DWORD mpg_cmd_fb_proc();
DWORD mpg_cmd_slow_proc();
DWORD mpg_cmd_stop_proc();
DWORD mpg_cmd_search_proc(DWORD search_time);
DWORD mpg_cmd_search_ms_proc(DWORD search_ms_time);
DWORD mpg_cmd_change_subtitle(INT32 sub_pid);
DWORD mpg_cmd_change_audio_track(INT32 *aud_pid);
DWORD mpg_cmd_change_prog (int prog_id);
DWORD MpgFileGetStreamInfo(PDEC_STREAM_INFO pDecStreamInfo);
DWORD MpgFileGetChapterInfo(PDEC_CHAPTER_INFO pDecChapterInfo);
DWORD MPGFileDecoderGetPlayTime();
DWORD MPGFileDecoderGetPlayTimeMS();
DWORD mpg_cmd_resume_stop_proc();
int MPGGetTotalPlayTime();
DWORD MPGGetTotalPlayTimeMS();
RET_CODE video_decoder_ioctl(unsigned long io_cmd, unsigned long param1, unsigned long param2);
AF_PE_PLAY_STATE get_next_play_state(void);
DWORD MpgSetAVSyncDelay(UINT32 stream_type, INT32 time_ms);
void video_set_disableSeek(UINT8 disable);

UINT32 video_engine_entry[] = 
{
    (UINT32)video_engine_init,
    (UINT32)video_engine_pe_cache_init,
    (UINT32)video_engine_decode,
    (UINT32)video_engine_set_output,
    (UINT32)mpg_cmd_play_proc,
    (UINT32)mpg_cmd_pause_proc,
    (UINT32)mpg_cmd_resume_proc,
    (UINT32)mpg_cmd_ff_proc,
    (UINT32)mpg_cmd_fb_proc,
    (UINT32)mpg_cmd_slow_proc,
    (UINT32)mpg_cmd_stop_proc,
    (UINT32)mpg_cmd_search_proc,
    (UINT32)mpg_cmd_change_audio_track,
    (UINT32)mpg_cmd_change_prog,
    (UINT32)MpgFileGetStreamInfo,
    (UINT32)MPGFileDecoderGetPlayTime,
    (UINT32)MPGGetTotalPlayTime,
    (UINT32)video_engine_pe_cache_release,
    (UINT32)mpg_cmd_search_ms_proc,
    (UINT32)mpg_cmd_resume_stop_proc,
    (UINT32)mpg_cmd_change_subtitle,
    (UINT32)MpgFileGetChapterInfo,
    (UINT32)video_decoder_ioctl,
    (UINT32)get_next_play_state,
    (UINT32)MPGGetTotalPlayTimeMS,
    (UINT32)MPGFileDecoderGetPlayTimeMS,
    (UINT32)MpgSetAVSyncDelay,
    (UINT32)video_set_disableSeek,
};

void lib_pe_adv_video_engine_callee(UINT8 *msg)
{
    OS_hld_callee(video_engine_entry, msg);
}

#endif

#ifdef _LIB_PE_ADV_VIDEO_ENGINE_REMOTE
static UINT32 desc_ve_init[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct pe_video_cfg)), 
  1, DESC_P_PARA(0, 0, 0),
  //desc of pointer ret
  0,                          
  0,
};

static UINT32 desc_ve_set_output[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct VDecPIPInfo)), 
  1, DESC_P_PARA(0, 1, 0),
  //desc of pointer ret
  0,                          
  0,
};

static UINT32 desc_ve_p_int32[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, 4),  
  1, DESC_P_PARA(0, 0, 0),
  //desc of pointer ret
  0,                          
  0,
};

static UINT32 desc_ve_get_stream_info[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(DEC_STREAM_INFO)),  
  1, DESC_P_PARA(0, 0, 0),
  //desc of pointer ret
  0,
  0,
};

static UINT32 desc_ve_get_chapter_info[] =
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(DEC_CHAPTER_INFO)),
  1, DESC_P_PARA(0, 0, 0),
  //desc of pointer ret
  0,
  0,
};

UINT32 desc_vdec_ioctl[] =
{ //desc of pointer para
  2, DESC_STATIC_STRU(0, 0), DESC_STATIC_STRU(1, 0),
  2, DESC_P_PARA(0, 1, 0), DESC_P_PARA(0, 2, 1),
  //desc of pointer ret
  0,
  0,
};

extern struct img_callback g_vde_cb;
static int video_engine_init_naked(struct pe_video_cfg *pe_video_cfg)
{
    g_vde_cb.mp_cb = pe_video_cfg->mp_cb;
    jump_to_func(NULL, OS_hld_caller, pe_video_cfg, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_INIT, desc_ve_init);

}

#ifdef _INVW_JUICE
INT32 mp4version_check(UINT8 para);
#endif
int video_engine_init(struct pe_video_cfg *pe_video_cfg)
{
#ifdef _INVW_JUICE
    mp4version_check(0);	
#endif
    return video_engine_init_naked(pe_video_cfg);
}

int video_engine_pe_cache_init(pe_cache_ex *pe_cache_info_ex, pe_cache_cmd *pe_cache_cmd_buf, ID pe_cache_mutex)
{
    jump_to_func(NULL, OS_hld_caller, pe_cache_info_ex, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(3<<16)|FUNC_VIDEO_ENGINE_PE_CACHE_INIT, NULL);
}

int video_engine_pe_cache_release()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_PE_CACHE_RELEASE, NULL);
}

static int video_engine_decode_naked(char *video_file, UINT8 video_stream_type, enum SndDupChannel audio_channel, BOOL preview)
{
    jump_to_func(NULL, OS_hld_caller, video_file, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(4<<16)|FUNC_VIDEO_ENGINE_DECODE, NULL);
}


int video_engine_decode(char *video_file, UINT8 video_stream_type, enum SndDupChannel audio_channel, BOOL preview)
{
    return video_engine_decode_naked(video_file, video_stream_type, audio_channel, preview);
}


int video_engine_set_output(enum VDecOutputMode eOutMode, struct VDecPIPInfo *pInitInfo)
{
    jump_to_func(NULL, OS_hld_caller, eOutMode, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(2<<16)|FUNC_VIDEO_ENGINE_SET_OUTPUT, desc_ve_set_output);
}

DWORD mpg_cmd_play_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_PLAY, NULL);
}

DWORD mpg_cmd_pause_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_PAUSE, NULL);
}

DWORD mpg_cmd_resume_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_RESUME, NULL);
}

DWORD mpg_cmd_ff_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_FF, NULL);
}

DWORD mpg_cmd_fb_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_FB, NULL);
}

DWORD mpg_cmd_slow_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_SLOW, NULL);
}

DWORD mpg_cmd_stop_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_STOP, NULL);
}

DWORD mpg_cmd_resume_stop_proc()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_CMD_RESUME_STOP, NULL);
}

DWORD mpg_cmd_search_proc(DWORD search_time)
{
    jump_to_func(NULL, OS_hld_caller, search_time, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_CMD_SEARCH, NULL);
}

DWORD mpg_cmd_search_ms_proc(DWORD search_ms_time)
{
    jump_to_func(NULL, OS_hld_caller, search_ms_time, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_CMD_SEARCH_MS, NULL);
}

DWORD mpg_cmd_change_audio_track(INT32 *aud_pid)
{
    jump_to_func(NULL, OS_hld_caller, aud_pid, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_CMD_CHANGE_AUDIO_TRACK, desc_ve_p_int32);
}

DWORD mpg_cmd_change_subtitle(INT32 sub_pid)
{
    jump_to_func(NULL, OS_hld_caller, sub_pid, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_CMD_CHANGE_SUBTITLE, NULL);
}

DWORD mpg_cmd_change_prog(int prog_id)
{
    jump_to_func(NULL, OS_hld_caller, prog_id, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_CMD_CHANGE_PROG, NULL);
}

DWORD MpgFileGetStreamInfo(PDEC_STREAM_INFO pDecStreamInfo)
{
    jump_to_func(NULL, OS_hld_caller, pDecStreamInfo, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_GET_STREAM_INFO, desc_ve_get_stream_info);
}

DWORD MpgFileGetChapterInfo(PDEC_CHAPTER_INFO pDecChapterInfo)
{
    jump_to_func(NULL, OS_hld_caller, pDecChapterInfo, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_ENGINE_GET_CHAPTER_INFO, desc_ve_get_chapter_info);
}

DWORD MPGFileDecoderGetPlayTime()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_GET_PLAY_TIME, NULL);
}

DWORD MPGFileDecoderGetPlayTimeMS()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_GET_PLAY_TIMEMS, NULL);
}

int MPGGetTotalPlayTime()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_GET_TOTAL_PLAY_TIME, NULL);
}

DWORD MPGGetTotalPlayTimeMS()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_GET_TOTAL_PLAY_TIMEMS, NULL);
}

DWORD MpgSetAVSyncDelay(UINT32 stream_type, INT32 time_ms)
{
    jump_to_func(NULL, OS_hld_caller, stream_type, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(2<<16)|FUNC_VIDEO_ENGINE_SET_AVSYNC_DELAY, NULL);
}

UINT32 desc_video_get_status[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct VDec_StatusInfo)),
  1, DESC_P_PARA(0, 1, 0), 
  //desc of pointer ret
  0,                          
  0,
};

RET_CODE video_decoder_ioctl(unsigned long io_cmd, unsigned long param1, unsigned long param2)
{
#ifdef SUPPORT_ES_PLAYER	
    UINT32 *desc = NULL;

    switch(io_cmd)
    {
        case VDEC_IO_SET_SCALE_MODE:
            break;
        case CONTAINER_IO_CONTROL_GET_TIME_MS:
            break;
        case VDEC_IO_GET_STATUS:
            desc = desc_video_get_status;
            break;
        case CONTAINER_IO_CONTROL_GET_CHAPTER_INFO:
            break;
        case CONTAINER_IO_CONTROL_EN_AC3_BS_MODE:
        default:
            break;
    }
#else  
    UINT32 i;
    UINT32 common_desc[sizeof(desc_vdec_ioctl)];

    MEMCPY(common_desc, desc_vdec_ioctl, sizeof(desc_vdec_ioctl));
    UINT32 *desc = (UINT32 *)common_desc;
    UINT32 *b = (UINT32 *)desc_vdec_ioctl;

    for(i = 0; i < sizeof(desc_vdec_ioctl)/sizeof(UINT32); i++)
    {
        desc[i] = b[i];
    }

    switch(io_cmd)
    {
        case VDEC_IO_SET_SCALE_MODE:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, 0);
            DESC_STATIC_STRU_SET_SIZE(common_desc, 1, sizeof(struct VDecPIPInfo));
            break;
        case CONTAINER_IO_CONTROL_GET_TIME_MS:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(unsigned long));
            break;
        case VDEC_IO_GET_STATUS:
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(struct  VDec_StatusInfo));
            break;
        case VDEC_IO_GET_MODE:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, 4);
            break;
        case CONTAINER_IO_CONTROL_GET_CHAPTER_INFO:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(DEC_CHAPTER_INFO));
            break;
        case CONTAINER_IO_CONTROL_SET_AVSYNC_DELAY:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, 0);
            DESC_STATIC_STRU_SET_SIZE(common_desc, 1, 0);
            break;

        case CONTAINER_IO_CONTROL_EN_AC3_BS_MODE:
        default:
            desc = NULL;
            break;
    }
#endif
    jump_to_func(NULL, OS_hld_caller, io_cmd, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(3<<16)|FUNC_VIDEO_ENGINE_DECODER_CONTROL, desc);
}


static UINT32 desc_vdec_cmd_init[] = 
{   //desc of pointer para
	1, DESC_STATIC_STRU(0, sizeof(VdecInit)),
	1, DESC_P_PARA(0, 3, 0), 
	//desc of pointer ret
	0,                          
	0,
};

static UINT32 desc_vdec_cmd_sw_reset[] = 
{   //desc of pointer para
	1, DESC_OUTPUT_STRU(0, sizeof(struct OutputFrmManager)),
	1, DESC_P_PARA(0, 3, 0),
	//desc of pointer ret
	0,                          
	0,
};

static UINT32 desc_vdec_display_rect[] = 
{   //desc of pointer para
	2, DESC_STATIC_STRU(0, sizeof(struct av_rect)), DESC_STATIC_STRU(1, sizeof(struct av_rect)),
	2, DESC_P_PARA(0, 2, 0), DESC_P_PARA(1, 3, 1),
	//desc of pointer ret
	0,                          
	0,
};

static UINT32 desc_vdec_cmd_get_status[] = 
{   //desc of pointer para
	1, DESC_OUTPUT_STRU(0, sizeof(struct vdec_decore_status)),
	1, DESC_P_PARA(0, 2, 0),
	//desc of pointer ret
	0,                          
	0,
};

static UINT32 desc_vdec_decore_uint32[] = 
{   //desc of pointer para
	2, DESC_OUTPUT_STRU(0, 4), DESC_OUTPUT_STRU(0, 4),
	2, DESC_P_PARA(0, 2, 0), DESC_P_PARA(1, 3, 1),
	//desc of pointer ret
	0,                          
	0,
};

static UINT32 desc_deca_decore_init[] = 
{   //desc of pointer para
	2, DESC_STATIC_STRU(0, sizeof(struct audio_config)), DESC_OUTPUT_STRU(1, 4),
	2, DESC_P_PARA(0, 1, 0), DESC_P_PARA(1, 2, 1),
	//desc of pointer ret
	0,                          
	0,
};

static UINT32 desc_deca_decore_uint32[] = 
{   //desc of pointer para
	2, DESC_OUTPUT_STRU(0, 4), DESC_OUTPUT_STRU(1, 4),
	2, DESC_P_PARA(0, 1, 0), DESC_P_PARA(1, 2, 1),
	//desc of pointer ret
	0,                          
	0,
};

AF_PE_PLAY_STATE get_next_play_state(void)
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(0<<16)|FUNC_VIDEO_ENGINE_GET_NEXT_STATE, NULL);
}

void video_set_disableSeek(UINT8 disable)
{
    jump_to_func(NULL, OS_hld_caller, disable, (LIB_PE_ADV_VIDEO_ENGINE_MODULE<<24)|(1<<16)|FUNC_VIDEO_SET_DISALBE_SEEK, NULL);
}

#endif

#endif

